﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Security.Permissions;
using SPMS.Utility;

namespace SPMS.Utility.Storage
{
    /// <summary>
    /// 可传递线程本地存储器
    /// </summary>
    /// <remarks>定义了可传递线程本地存储器。可传递线程本地存储器会将存储的值传递到当前线程的子线程中去。</remarks>
    /// <history>
    /// [ZaneZeng]               2009-5-20 12:22    创建
    /// </history>
    [SecurityPermission( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure )]
    public sealed class InheritableThreadLocalStorage : INamedStorage
    {
        #region ---Public Method

        /// <summary>
        /// 从当前线程本地存储器中获得与给定名称关联的数据
        /// </summary>
        /// <param name="name">线程本地存储器中数据项的名称</param>
        /// <returns>线程本地存储器中存储的与给定名称关联的数据项</returns>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-20 12:25    创建
        /// </history>
        public object GetData( string name )
        {
            //判断名称是否为空
            if (string.IsNullOrEmpty( name ))
            {
                //如果名称为空，则返回NULL
                return null;
            }

            //用于保存数据
            object data;

            //从数据映射表中获得数据
            if (this.DataMap.TryGetValue( name, out data ))
            {
                //如果数据存在，则返回获得的数据项
                return data;
            }

            //如果不存在，则返回NULL
            return null;
        }

        /// <summary>
        /// 以给定的名称项当前线程本地存储中添加给定数据项
        /// </summary>
        /// <param name="name">数据项关联的名称</param>
        /// <param name="data">要添加的数据项</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为Null或者为空字符串</exception>
        /// <history>
        /// [ZaneZeng]               2009-5-20 12:26    创建
        /// </history>
        public void SetData( string name, object data )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( name, "name" );

            //保存到数据映射表
            this.DataMap[name] = data;
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得数据映射表
        /// </summary>
        /// <value></value>
        /// <returns>获得的数据映射表</returns>
        /// <remarks></remarks>
        /// <history>
        /// [ZaneZeng]               2009-5-20 13:53    创建
        /// </history>
        private Dictionary<string, object> DataMap
        {
            get
            {
                //从当前线程的逻辑上下文中获得数据映射
                Dictionary<string, object> map = CallContext.LogicalGetData( this.m_LogicalDataName ) as Dictionary<string, object>;

                //判断数据映射表是否存在
                if (null == map)
                {
                    //如果不存在，则创建数据映射
                    map = new Dictionary<string, object>();

                    //添加到逻辑调用上下文
                    CallContext.LogicalSetData( this.m_LogicalDataName, map );
                }

                //返回数据映射表
                return map;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 逻辑数据名称
        /// </summary>
        private string m_LogicalDataName = Guid.NewGuid().ToString();

        #endregion
    }
}
